import type { DragEndEvent } from "@dnd-kit/core"
import { DndContext, PointerSensor, useSensor } from "@dnd-kit/core"
import {
  arrayMove,
  horizontalListSortingStrategy,
  SortableContext,
  useSortable
} from "@dnd-kit/sortable"
import { CSS } from "@dnd-kit/utilities"
import React, { useEffect, useState } from "react"
import { Tabs, TabsProps } from "antd"
import { restrictToHorizontalAxis } from "@dnd-kit/modifiers"
import "./style.less"

interface DraggableTabPaneProps extends React.HTMLAttributes<HTMLDivElement> {
  "data-node-key": string
}

const DraggableTabNode = (props: DraggableTabPaneProps) => {
  const { attributes, listeners, setNodeRef, transform, transition } = useSortable({
    id: props["data-node-key"]
  })

  const style: React.CSSProperties = {
    ...props.style,
    transform: CSS.Transform.toString(transform && { ...transform, scaleX: 1 }),
    transition
  }

  return React.cloneElement(props.children as React.ReactElement, {
    ref: setNodeRef,
    style,
    ...attributes,
    ...listeners
  })
}
const DraggableTab: React.FC<TabsProps & { onItemsChange?: (items: any[]) => void }> = ({
  onItemsChange,
  ...props
}) => {
  const [items, setItems] = useState(props.items || [])

  const sensor = useSensor(PointerSensor, { activationConstraint: { distance: 10 } })

  const onDragEnd = ({ active, over }: DragEndEvent) => {
    if (active.id !== over?.id) {
      setItems((prev) => {
        const activeIndex = prev.findIndex((i) => i.key === active.id)
        const overIndex = prev.findIndex((i) => i.key === over?.id)
        return arrayMove(prev, activeIndex, overIndex)
      })
    }
  }

  useEffect(() => {
    setItems(props.items || [])
  }, [props.items])

  useEffect(() => {
    if (onItemsChange) {
      onItemsChange(items)
    }
  }, [items])

  return (
    <Tabs
      renderTabBar={(tabBarProps, DefaultTabBar) => (
        <DndContext sensors={[sensor]} onDragEnd={onDragEnd} modifiers={[restrictToHorizontalAxis]}>
          <SortableContext items={items.map((i) => i.key)} strategy={horizontalListSortingStrategy}>
            <DefaultTabBar {...tabBarProps}>
              {(node) => (
                <DraggableTabNode {...node.props} key={node.key}>
                  {node}
                </DraggableTabNode>
              )}
            </DefaultTabBar>
          </SortableContext>
        </DndContext>
      )}
      {...props}
      items={items}
      className="tab-layout"
    />
  )
}

export default DraggableTab
